package com.turing.post.util;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;


public class DESUtil {
	public static byte[] encrypt(byte[] key, byte[] data) {
		byte[] result = null;
		try {
			SecretKey secretKey = getSecretKeySpec(key);
			Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
			cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(
					new byte[8]));
			result = cipher.doFinal(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 16杩涘埗瀛楃涓插姞瀵�
	 * 
	 * @param key
	 *            16浣嶉暱
	 * @param data
	 *            16浣嶉暱
	 * @return
	 */
	public static String encrypt(String key, String data) {
		return PCPSUtil.getHexString(encrypt(PCPSUtil.getBytes(key), PCPSUtil
				.getBytes(data)));
	}

	/**
	 * 浜х敓8瀛楄妭鐨勮繃绋嬪瘑閽�
	 * 
	 * @param key
	 *            (16)
	 * @param data
	 * @return
	 */
	public static String genSK(String key, String data) {
		byte[] kl = PCPSUtil.getBytes(key.substring(0, 16));
		byte[] kr = PCPSUtil.getBytes(key.substring(16, 32));
		byte[] bd = PCPSUtil.getBytes(data);
		byte[] round1 = encrypt(kl, bd);
		byte[] round2 = decrypt(kr, round1);
		byte[] round3 = encrypt(kl, round2);
		return PCPSUtil.getHexString(round3);
	}

	private static byte[] execXOR(byte[] src, int off, byte[] iv) {
		byte[] dst = new byte[8];

		for (int i = 0; i < 8; i++)
			dst[i] = (byte) (src[off + i] ^ iv[i]);

		return dst;
	}

	/**
	 * 浜х敓4瀛楄妭鐨凪AC
	 * 
	 * @param sk
	 *            (8)
	 * @param data
	 *            (闇�瑕佽繘琛屽榻�)
	 * @return
	 */
	public static String genMAC(String sk, String data) {
		// 鎸夌収瑙勮寖杩涜鍧楀榻愭搷浣�
		String userdata = data;
		int left = data.length() % 16;
		if (left == 0)
			userdata = data + "8000000000000000";
		else {
			userdata += "80";
			while ((userdata.length() % 16) != 0)
				userdata += "00";
		}
		byte[] usk = PCPSUtil.getBytes(sk);
		byte[] macdata = PCPSUtil.getBytes(userdata);
		byte[] iv = PCPSUtil.getBytes("0000000000000000");
		for (int i = 0; i < macdata.length / 8; i++) {
			byte[] ud = execXOR(macdata, i * 8, iv);
			iv = encrypt(usk, ud);
		}
		return PCPSUtil.getHexString(iv, 0, 4);
	}

	/**
	 * 浜х敓TAC
	 * 
	 * @param dtk
	 * @param data
	 * @return
	 */
	public static String genTAC(String dtk, String data) {
		byte[] kl = PCPSUtil.getBytes(dtk.substring(0, 16));
		byte[] kr = PCPSUtil.getBytes(dtk.substring(16, 32));
		byte[] tackey = execXOR(kl, 0, kr);
		return genMAC(PCPSUtil.getHexString(tackey), data);
	}

	/**
	 * 浜х敓瀹夊叏鎶ユ枃MAC
	 * 
	 * @param dcmk
	 *            鍙屽�嶉暱
	 * @param macrnd
	 *            4瀛楄妭闅忔満鏁�
	 * @param data
	 *            寰呬骇鐢焟ac鐨勬暟鎹洜瀛�
	 * @return
	 */
	public static String genMsgMac(String dcmk, String macrnd, String data) {
		// 鎸夌収瑙勮寖杩涜鍧楀榻愭搷浣�
		String userdata = data;
		int left = data.length() % 16;
		if (left == 0)
			userdata = data + "8000000000000000";
		else {
			userdata += "80";
			while ((userdata.length() % 16) != 0)
				userdata += "00";
		}
		byte[] mk_l = PCPSUtil.getBytes(dcmk.substring(0, 16));
		byte[] mk_r = PCPSUtil.getBytes(dcmk.substring(16, 32));
		byte[] macdata = PCPSUtil.getBytes(userdata);
		byte[] iv = PCPSUtil.getBytes(macrnd + "00000000");

		for (int i = 0; i < macdata.length / 8; i++) {
			byte[] ud = execXOR(macdata, i * 8, iv);
			iv = encrypt(mk_l, ud);
		}

		iv = decrypt(mk_r, iv);
		iv = encrypt(mk_l, iv);

		return PCPSUtil.getHexString(iv, 0, 4);
	}

	public static byte[] decrypt(byte[] key, byte[] data) {
		byte[] result = null;
		try {
			SecretKey secretKey = getSecretKeySpec(key);
			Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
			cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(
					new byte[8]));
			result = cipher.doFinal(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 16杩涘埗瀛楃涓插姞瀵�
	 * 
	 * @param key
	 *            16浣嶉暱
	 * @param data
	 *            16浣嶉暱
	 * @return
	 */
	public static String decrypt(String key, String data) {
		return PCPSUtil.getHexString(decrypt(PCPSUtil.getBytes(key), PCPSUtil
				.getBytes(data)));
	}

	private static SecretKey getSecretKeySpec(byte[] keyB)
			throws NoSuchAlgorithmException, InvalidKeySpecException,
			InvalidKeyException {
		// 瀹炰緥鍖朌ES瀵嗛挜瑙勫垯
		DESKeySpec dks = new DESKeySpec(keyB);
		// 瀹炰緥鍖栧瘑閽ュ伐鍘�
		SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
		// 鐢熸垚瀵嗛挜
		SecretKey secretKey = skf.generateSecret(dks);
		return secretKey;
	}

//	public static void main(String[] args) throws Exception {
//		System.out.println(encrypt("0000000000000000", "0123456789ABCDEF"));
//		System.out.println(decrypt("0000000000000000", "617B3A0CE8F07100"));
//
//		System.out.println(genSK(CardApdu.DEFAULT_KEY_16, "74636153" + "0000"
//				+ "8000"));
//
//		System.out.println("MAC1:"
//				+ genMAC("C57D230D2DF2A04D", "000000000000000102139918175600"));
//		System.out.println("MAC2:"
//				+ genMAC("C57D230D2DF2A04D",
//						"000000010213991817560020130101121314"));
//		System.out.println("TAC:"
//				+ genTAC(CardApdu.DEFAULT_KEY_16,
//						"000000010000000000010213991817560020130101121314"));
//		System.out.println("MSG_MAC:"
//				+ genMsgMac("57415443484441544154696D65434F53", "464E84AF",
//						"04D6830014687E0F83F6A98580C4015CEB8D00F38B"));
//
//		System.out.println(PCPSUtil.encodeAscToHexString("鏉ㄦ柊鏂�", 4));
//		System.out.println(PCPSUtil.decodeHexStringToAsc("D1EED0C2", 4, 4));
//	}
}
